package com.canaan.business.service.storehouse.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.canaan.business.common.enums.agv.AgvEnum;
import com.canaan.business.common.enums.basic.YNEnum;
import com.canaan.business.common.enums.inOutStock.ErpBillTypeEnum;
import com.canaan.business.common.enums.inOutStock.InOrderStatusEnum;
import com.canaan.business.common.enums.inOutStock.InOutStockTypeEnum;
import com.canaan.business.common.enums.inOutStock.OutOrderStatusEnum;
import com.canaan.business.common.enums.storehouse.InOutStorageOperationEnum;
import com.canaan.business.common.enums.storehouse.StorehouseStockStatusEnum;
import com.canaan.business.domain.agv.AgvTaskDispatch;
import com.canaan.business.domain.basic.ErpProduct;
import com.canaan.business.domain.basic.WmsProduct;
import com.canaan.business.domain.basic.WmsStorehouseLocation;
import com.canaan.business.domain.bill.*;
import com.canaan.business.domain.bo.InventoryOverviewBo;
import com.canaan.business.domain.inOutStock.*;
import com.canaan.business.domain.storehouse.*;
import com.canaan.business.domain.vo.InventoryOverviewVo;
import com.canaan.business.domain.vo.OutStockQueryVo;
import com.canaan.business.domain.vo.StorehouseStockAdjustDetailVo;
import com.canaan.business.domain.vo.WmsStorehouseStockVo;
import com.canaan.business.mapper.storehouse.WmsStorehouseStockMapper;
import com.canaan.business.service.agv.IAgvTaskDispatchService;
import com.canaan.business.service.basic.IErpProductService;
import com.canaan.business.service.basic.IWmsProductService;
import com.canaan.business.service.basic.IWmsStorehouseLocationService;
import com.canaan.business.service.bill.*;
import com.canaan.business.service.inOutStock.*;
import com.canaan.business.service.storehouse.IInventoryAlertService;
import com.canaan.business.service.storehouse.IStockStageService;
import com.canaan.business.service.storehouse.IWmsInOutStorageService;
import com.canaan.business.service.storehouse.IWmsStorehouseStockService;
import com.canaan.common.core.domain.AjaxResult;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.common.utils.TableNoUtil;
import com.canaan.system.service.impl.SysUserServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 库存Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-30
 */
@Service
public class WmsStorehouseStockServiceImpl implements IWmsStorehouseStockService {

    private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);

    @Resource
    private WmsStorehouseStockMapper wmsStorehouseStockMapper;
    @Resource
    private IWmsStorehouseLocationService wmsStorehouseLocationService;
    @Autowired
    private IWmsProductService wmsProductService;
    @Autowired
    private IWmsInOutStorageService wmsInOutStorageService;
    @Autowired
    private IStockStageService stockStageService;
    @Autowired
    private IInventoryAlertService inventoryAlertService;
    @Resource
    private IInStockBillService inStockBillService;
    @Resource
    private IOutStockBillService outStockBillService;
    @Resource
    private IReceiveProductBillService receiveProductBillService;
    @Resource
    private IPurchaseReturnBillService purchaseReturnBillService;
    @Resource
    private IAdjustInBillService adjustInBillService;
    @Resource
    private IAdjustOutBillService adjustOutBillService;
    @Resource
    private IAdjustLocationBillService adjustLocationBillService;
    @Resource
    private IModulationInBillService modulationInBillService;
    @Resource
    private IModulationOutBillService modulationOutBillService;
    @Resource
    private ITrayService trayService;
    @Resource
    private ITrayDetailService trayDetailService;
    @Resource
    private IReturnStockBillService returnStockBillService;
    @Resource
    private IAgvTaskDispatchService agvTaskDispatchService;
    @Resource
    private IBindRecordService bindRecordService;
    @Resource
    private IErpProductService erpProductService;

    @Resource
    private ISplitBillService splitBillService;
    /**
     * 查询库存
     *
     * @param id 库存主键
     * @return 库存
     */
    @Override
    public WmsStorehouseStock selectWmsStorehouseStockById(Long id)
    {
        return wmsStorehouseStockMapper.selectWmsStorehouseStockById(id);
    }

    /**
     * 根据条码获取库存信息
     *
     * @param barcode 条码
     * @return 库存
     */
    @Override
    public WmsStorehouseStock getInfoByBarcode(String barcode)
    {
        WmsStorehouseStock stock  = wmsStorehouseStockMapper.selectWmsStorehouseStockListByBarcode(barcode);
        if(stock == null){
            throw new ServiceException(barcode+"：条码不存在");
        }else if(StorehouseStockStatusEnum.FREEZE.getCode().equals(stock.getStatus())){
            throw new ServiceException(barcode+"：该库存已被冻结");
        }else if(StorehouseStockStatusEnum.LOCK.getCode().equals(stock.getStatus())){
            throw new ServiceException(barcode+"：该库存已被锁定");
        }
        return stock;
    }

    @Override
    public WmsStorehouseStock getCheckByBarcode(String barcode) {
        WmsStorehouseStock stock = new WmsStorehouseStock();
        stock.setBarcode(barcode);
        List<WmsStorehouseStock> list = wmsStorehouseStockMapper.selectWmsStorehouseStockList(stock);
        if(list.isEmpty()){
            throw new ServiceException("条码不存在");
        }
        stock = list.get(0);
        return stock;
    }

    /**
     * 根据库位获取库存信息列表
     *
     * @param barcodes 库位列表
     * @return 库存
     */
    @Override
    public List<WmsStorehouseStock> getListByBarcodes(List<String> barcodes)
    {
        if(barcodes == null || barcodes.isEmpty()){
            return Collections.emptyList();
        }
        return this.wmsStorehouseStockMapper.getListByBarcodes(barcodes);
    }

    @Override
    public List<WmsStorehouseStock> getListByQualityTaskNo(String qualityTaskNo) {
        WmsStorehouseStock query = new WmsStorehouseStock();
        query.setQualityTaskNo(qualityTaskNo);
        return wmsStorehouseStockMapper.selectWmsStorehouseStockList(query);
    }

    /**
     * 根据库位获取库存信息
     *
     * @param locationNo 库位
     * @return 库存
     */
    @Override
    public WmsStorehouseStock getInfoByLocationNo(String locationNo)
    {
        List<WmsStorehouseStock> list = wmsStorehouseStockMapper.getListByLocationNos(Collections.singletonList(locationNo));
        if(list.isEmpty()){
            WmsStorehouseLocation location = wmsStorehouseLocationService.selectWmsStorehouseLocationByNo(locationNo);
            if(location == null) {
                throw new ServiceException("库位不存在");
            }
            WmsStorehouseStock storehouseStock = new WmsStorehouseStock();
            storehouseStock.setStorehouseNo(location.getStorehouseNo());
            storehouseStock.setStorehouseAreaNo(location.getStorehouseAreaNo());
            storehouseStock.setStorehouseLocationNo(location.getNo());
            storehouseStock.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
            storehouseStock.setIsCheckLock(YNEnum.N.getCode());
            return storehouseStock;
        }
        WmsStorehouseStock stock = list.get(0);
//        if(StorehouseStockStatusEnum.FREEZE.getCode().equals(stock.getStatus())){
//            throw new ServiceException("该库存已被冻结");
//        }
//        else
            if(StorehouseStockStatusEnum.LOCK.getCode().equals(stock.getStatus())){
            throw new ServiceException("该库存库位已被锁定，不允许出入库");
         }
        return stock;
    }

    /**
     * 根据库位获取库存信息列表
     *
     * @param locationNos 库位列表
     * @return 库存
     */
    @Override
    public List<WmsStorehouseStock> getListByLocationNos(List<String> locationNos)
    {
        if(locationNos == null || locationNos.isEmpty()){
            return Collections.emptyList();
        }
        return this.wmsStorehouseStockMapper.getListByLocationNos(locationNos);
    }

    /**
     * 查询库存列表
     *
     * @param wmsStorehouseStock 库存
     * @return 库存
     */
    @Override
    public List<WmsStorehouseStock> selectWmsStorehouseStockList(WmsStorehouseStock wmsStorehouseStock)
    {
        return wmsStorehouseStockMapper.selectWmsStorehouseStockList(wmsStorehouseStock);
    }

    @Override
    public List<WmsStorehouseStock> selectNewWmsStorehouseStockListPageData(WmsStorehouseStock wmsStorehouseStock) {
        List<WmsStorehouseStock> list = wmsStorehouseStockMapper.selectNewWmsStorehouseStockListPageDatas(wmsStorehouseStock);
        if (CollectionUtil.isEmpty(list) && StringUtils.isNotEmpty(wmsStorehouseStock.getProductNo())) {
            ErpProduct product = erpProductService.selectErpProductByBarCode(wmsStorehouseStock.getProductNo());
            if(product == null){
                return list;
            }
            wmsStorehouseStock.setProductNo(product.getProductNo());
            list = wmsStorehouseStockMapper.selectNewWmsStorehouseStockListPageDatas(wmsStorehouseStock);
        }
        return list;
    }

    /**
     * 查询库存列表
     *
     * @param wmsStorehouseStock 库存
     * @return 库存
     */
    @Override
    public List<WmsStorehouseStock> selectNewWmsStorehouseStockList(WmsStorehouseStock wmsStorehouseStock)
    {
        return wmsStorehouseStockMapper.selectNewWmsStorehouseStockList(wmsStorehouseStock);
    }

    /**
     * 新增库存
     *
     * @param wmsStorehouseStock 库存
     * @return 结果
     */
    @Override
    public int insertWmsStorehouseStock(WmsStorehouseStock wmsStorehouseStock)
    {
        wmsStorehouseStock.setNo(TableNoUtil.getNo(WmsStorehouseStock.class));
        wmsStorehouseStock.setCreateBy(SecurityUtils.getUsername());
        wmsStorehouseStock.setCreateTime(DateUtils.getNowDate());
        return wmsStorehouseStockMapper.insertWmsStorehouseStock(wmsStorehouseStock);
    }

    /**
     * 批量新增库存
     *
     * @param storehouseStockList 库存列表
     * @return 结果
     */
    @Override
    public int batchInsertWmsStorehouseStock(List<WmsStorehouseStock> storehouseStockList) {
        String username = SecurityUtils.getUsername();
        Date currerTime = DateUtils.getNowDate();
        for (WmsStorehouseStock storehouseStock : storehouseStockList){
            if(StringUtils.isBlank(storehouseStock.getNo())){
                storehouseStock.setNo(TableNoUtil.getNo(WmsStorehouseStock.class));
            }
            storehouseStock.setCreateBy(username);
            storehouseStock.setCreateTime(currerTime);
        }
        int insertNum = 0;
        for (int i=0; i<storehouseStockList.size();) {
            int endIndex = i+500;
            if (endIndex > storehouseStockList.size()) {
                endIndex = storehouseStockList.size();
            }
            insertNum = insertNum + wmsStorehouseStockMapper.batchInsertWmsStorehouseStock(storehouseStockList.subList(i, endIndex));
            i = endIndex;
        }
        return insertNum;
    }

    /**
     * 修改库存
     *
     * @param wmsStorehouseStock 库存
     * @return 结果
     */
    @Override
    public int updateWmsStorehouseStock(WmsStorehouseStock wmsStorehouseStock)
    {
        wmsStorehouseStock.setUpdateTime(DateUtils.getNowDate());
        return wmsStorehouseStockMapper.updateWmsStorehouseStock(wmsStorehouseStock);
    }

    /**
     * 批量修改库存
     *
     * @param storehouseStockList 库存列表
     * @return 结果
     */
    @Override
    public int batchUpdateWmsStorehouseStock(List<WmsStorehouseStock> storehouseStockList) {
        String username = SecurityUtils.getUsername();
        Date currerTime = DateUtils.getNowDate();
        for (WmsStorehouseStock storehouseStock : storehouseStockList){
            storehouseStock.setUpdateBy(username);
            storehouseStock.setUpdateTime(currerTime);
        }
        int updateNum = 0;
        for (int i=0; i<storehouseStockList.size();) {
            int endIndex = i+500;
            if (endIndex > storehouseStockList.size()) {
                endIndex = storehouseStockList.size();
            }
            updateNum = updateNum + wmsStorehouseStockMapper.batchUpdateWmsStorehouseStock(storehouseStockList.subList(i, endIndex));
            i = endIndex;
        }
        return updateNum;
    }

    /**
     * 批量删除库存
     *
     * @param ids 需要删除的库存主键
     * @return 结果
     */
    @Override
    public int deleteWmsStorehouseStockByIds(Long[] ids)
    {
        return wmsStorehouseStockMapper.deleteWmsStorehouseStockByIds(ids);
    }

    /**
     * 删除库存信息
     *
     * @param id 库存主键
     * @return 结果
     */
    @Override
    public int deleteWmsStorehouseStockById(Long id)
    {
        return wmsStorehouseStockMapper.deleteWmsStorehouseStockById(id);
    }

    @Override
    public List<WmsStorehouseStock> selectWmsStorehouseStockListByProductNo(String productNo) {
        WmsStorehouseStock storehouseStock = new WmsStorehouseStock();
        storehouseStock.setProductNo(productNo);
        return this.selectWmsStorehouseStockList(storehouseStock);
    }

    @Override
    public List<WmsStorehouseStock> selectWmsStorehouseStockListByLocationNo(String locationNo) {
        WmsStorehouseStock storehouseStock = new WmsStorehouseStock();
        storehouseStock.setStorehouseLocationNo(locationNo);
        return this.selectWmsStorehouseStockList(storehouseStock);
    }

    @Override
    public WmsStorehouseStock selectWmsStorehouseStockByLocationNo(String locationNo) {
        WmsStorehouseStock storehouseStock = new WmsStorehouseStock();
        storehouseStock.setStorehouseLocationNo(locationNo);
        storehouseStock.setDelFlag("0");
        List<WmsStorehouseStock> storehouseStocks= selectWmsStorehouseStockList(storehouseStock);
        if(storehouseStocks!=null&&storehouseStocks.size()!=0){
            return storehouseStocks.get(0);
        }
        else{
            return null;
        }
    }

    @Override
    public WmsStorehouseStock selectWmsStorehouseStockListByBarcode(String barcode) {
        return this.wmsStorehouseStockMapper.selectWmsStorehouseStockListByBarcode(barcode);
    }

    @Override
    public WmsStorehouseStock selectWmsStorehouseStockByTrayNo(String trayNo) {
        return this.wmsStorehouseStockMapper.selectWmsStorehouseStockByTrayNo(trayNo);
    }

    @Override
    public List<WmsStorehouseStock> selectWmsStorehouseStockListByStorehouse(WmsStorehouseStock wmsStorehouseStock) {
        List<WmsStorehouseStock> storehouseStocks = wmsStorehouseStockMapper.selectWmsStorehouseStockList(wmsStorehouseStock);
        return storehouseStocks.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WmsStorehouseStock::getProductNo))), ArrayList::new));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(List<WmsStorehouseStock> fileDataList) {
        if (StringUtils.isNull(fileDataList) || fileDataList.size() == 0) {
            throw new ServiceException("导入数据不能为空！");
        }
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        List<WmsStorehouseStock> addList = new ArrayList<>();
        List<WmsInOutStorage> addRecordList = new ArrayList<>();
        List<String> fileProductNos = new ArrayList<>();
        List<String> fileBarcodes = new ArrayList<>();
        List<String> fileLocationNos = new ArrayList<>();
        // 查询文档中的条码，用于校验是否已经存在
        WmsStorehouseStock searchCodeParam = new WmsStorehouseStock();
        searchCodeParam.setBarcodes(fileBarcodes);
        List<WmsStorehouseStock> fileBarcodeList = this.selectWmsStorehouseStockList(searchCodeParam);
        List<String> checkCodeList = new ArrayList<>();
        if (!fileBarcodeList.isEmpty()){
            checkCodeList = fileBarcodeList.stream().map(WmsStorehouseStock::getBarcode).collect(Collectors.toList());
        }
        // 循环校验必填
        for (int i = 0; i < fileDataList.size(); i++) {
            WmsStorehouseStock fileEntity = fileDataList.get(i);
            int rowNum = i + 2;
            if (StringUtils.isEmpty(fileEntity.getBarcode())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行条码不能为空");
                break;
            }else if (fileBarcodes.contains(fileEntity.getBarcode())){
                failureNum++;
                failureMsg.append("第" + rowNum + "行条码在文档中存在重复");
                break;
            }else if (checkCodeList.contains(fileEntity.getBarcode())){
                failureNum++;
                failureMsg.append("第" + rowNum + "行条码在系统中存在重复");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getProductNo())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行物料编号不能为空");
                break;
            }
            if (fileEntity.getQty() == null) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行库存数量不能为空");
                break;
            }
            if (StringUtils.isEmpty(fileEntity.getStorehouseLocationNo())) {
                failureNum++;
                failureMsg.append("第" + rowNum + "行库位编号不能为空");
                break;
            }else if (fileLocationNos.contains(fileEntity.getStorehouseLocationNo())){
                failureNum++;
                failureMsg.append("第" + rowNum + "行库位编号在文档中有重复");
                break;
            }
            if (!fileProductNos.contains(fileEntity.getProductNo())) {
                fileProductNos.add(fileEntity.getProductNo());
            }
            fileBarcodes.add(fileEntity.getBarcode());
            fileLocationNos.add(fileEntity.getStorehouseLocationNo());
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！");
            throw new ServiceException(failureMsg.toString());
        }
        WmsProduct searchWmsProduct = new WmsProduct();
        searchWmsProduct.setProductNos(fileProductNos);
        // 查询文档中存在的所有物料
        List<WmsProduct> allProductList = this.wmsProductService.selectWmsProductList(searchWmsProduct);
        // key:物料编号  value:实体类
        Map<String, WmsProduct> productMap = allProductList.stream().collect(Collectors.toMap(WmsProduct::getProductNo, Function.identity(), (key1, key2) -> key2));

        // 查询文档中存在的所有库位
        WmsStorehouseLocation searchLocation = new WmsStorehouseLocation();
        searchLocation.setNos(fileLocationNos);
        List<WmsStorehouseLocation> fileLocationList = this.wmsStorehouseLocationService.selectWmsStorehouseLocationList(searchLocation);
        // key:库位编号  value:实体类
        Map<String, WmsStorehouseLocation> locationMap = fileLocationList.stream().collect(Collectors.toMap(WmsStorehouseLocation::getNo, Function.identity(), (key1, key2) -> key2));

        // 循环判断物料、库位是否存在，赋值新增的数据
        for (int i = 0; i < fileDataList.size(); i++) {
            WmsStorehouseStock fileEntity = fileDataList.get(i);
            int rowNum = i + 2;
            try {
                // 物料编号验证是否存在物料
                WmsProduct product = productMap.get(fileEntity.getProductNo());

                if (product == null) {
                    failureNum++;
                    failureMsg.append("第" + rowNum + "行物料编号 " + fileEntity.getProductNo() + " 在系统中不存在");
                    break;
                }
                // 物料编号验证是否存在物料
                WmsStorehouseLocation wmsStorehouseLocation = locationMap.get(fileEntity.getStorehouseLocationNo());

                if (wmsStorehouseLocation == null) {
                    failureNum++;
                    failureMsg.append("第" + rowNum + "行库位编号 " + fileEntity.getStorehouseLocationNo() + " 在系统中不存在");
                    break;
                }
                WmsStorehouseStock addEntity = new WmsStorehouseStock();
                addEntity.setBarcode(fileEntity.getBarcode());
                addEntity.setStorehouseNo(wmsStorehouseLocation.getStorehouseNo());
                addEntity.setStorehouseAreaNo(wmsStorehouseLocation.getStorehouseAreaNo());
                addEntity.setStorehouseLocationNo(wmsStorehouseLocation.getNo());
                addEntity.setProductNo(product.getProductNo());
                addEntity.setProductName(product.getProductName());
                addEntity.setProductVersion(product.getProductVersion());
                addEntity.setBatchNo(fileEntity.getBatchNo());
                addEntity.setQty(fileEntity.getQty());
                addEntity.setProductionDate(fileEntity.getProductionDate());
                addEntity.setValidDateNum(fileEntity.getValidDateNum());
                addEntity.setEffectiveDate(fileEntity.getEffectiveDate());
                addEntity.setSupplierName(fileEntity.getSupplierName());
                addEntity.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
                addEntity.setIsCheckLock(YNEnum.N.getCode());
                addList.add(addEntity);

                // 需要增加一条入库记录
                WmsInOutStorage inOutStorage = new WmsInOutStorage();
                inOutStorage.setBarcode(addEntity.getBarcode());
                inOutStorage.setBatchNo(addEntity.getBatchNo());
                inOutStorage.setProductNo(addEntity.getProductNo());
                inOutStorage.setProductName(addEntity.getProductName());
                inOutStorage.setProductUnit(product.getCompany());
                inOutStorage.setQuantity(addEntity.getQty());
                inOutStorage.setStorehouseLocationNo(addEntity.getStorehouseLocationNo());
                inOutStorage.setStorehouseNo(addEntity.getStorehouseNo());
                inOutStorage.setAreaNo(addEntity.getStorehouseAreaNo());
                inOutStorage.setOperation(InOutStorageOperationEnum.IN.getCode());
                inOutStorage.setType(InOutStockTypeEnum.INIT.getCode().longValue());
                addRecordList.add(inOutStorage);

            } catch (Exception e) {
                failureNum++;
                String msg = "<br/> 第" + rowNum + "行数据有误，导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
                break;
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "导入失败！");
            throw new ServiceException(failureMsg.toString());
        }

        if (!CollectionUtils.isEmpty(addList)){
            this.batchInsertWmsStorehouseStock(addList);
            this.wmsInOutStorageService.batchInsertInOutStorage(addRecordList);
        }
        int addCount = addList.size();
        successMsg.insert(0, "导入成功！共新增 " + addCount + " 条数据");
        return successMsg.toString();
    }


    /**
     * 库存报警
     *
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void inventoryAlert() {
        // 查出所有物料的库存
        List<WmsStorehouseStock> allProductStock = this.wmsStorehouseStockMapper.getAllMaterialStock();
        if (CollectionUtils.isEmpty(allProductStock)){
            return;
        }
        List<String> productNos = allProductStock.stream().map(WmsStorehouseStock::getProductNo).distinct().collect(Collectors.toList());
        // 查询所有物料的库存水位
        StockStage searchStage = new StockStage();
        searchStage.setProductNos(productNos);
        List<StockStage> allStockStage = this.stockStageService.selectStockStageList(searchStage);
        // key->物料编号   value->库存水位信息
        Map<String,StockStage> stageMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(allStockStage)){
            stageMap = allStockStage.stream().collect(Collectors.toMap(StockStage::getProductNo, Function.identity(), (key1, key2) -> key2));
        }
        // 查询所有物料类型的库存水位
        StockStage searchTypeStage = new StockStage();
        searchTypeStage.setProductIsNull(YNEnum.Y.getCode());
        List<StockStage> allProductTypeStage = this.stockStageService.selectStockStageList(searchStage);
        // key->物料类型   value->库存水位信息
        Map<String,StockStage> typeStageMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(allProductTypeStage)){
            typeStageMap = allStockStage.stream().collect(Collectors.toMap(StockStage::getProductType, Function.identity(), (key1, key2) -> key2));
        }
        //获取物料信息
        List<WmsProduct> allStockProductInfo = wmsProductService.selectWmsProductsByProductNos(productNos);
        Map<String,WmsProduct> productMap = allStockProductInfo.stream().collect(Collectors.toMap(WmsProduct::getProductNo, Function.identity(), (key1, key2) -> key2));
        List<InventoryAlert> inventoryAlertAddList = new ArrayList<>();
        //按仓库分组库存数据
        Map<String, List<WmsStorehouseStock>>  storehouseMap=  allProductStock.stream().collect(Collectors.groupingBy(WmsStorehouseStock::getStorehouseNo));
        for (String item:storehouseMap.keySet()) {
            List<WmsStorehouseStock> storehouseStockList = storehouseMap.get(item);
            // 循环库存，判断是否低于最低库存
            for (WmsStorehouseStock wmsStorehouseStock : storehouseStockList) {
                StockStage stockStage = stageMap.get(wmsStorehouseStock.getProductNo());
                // 如果未维护该物料的水位，改为查询该物料类型的水位,如果仍未维护则跳过
                if (stockStage == null){
                    WmsProduct wmsProduct = productMap.get(wmsStorehouseStock.getProductNo());
                    stockStage = typeStageMap.get(wmsProduct.getProductType());
                    if (stockStage == null){
                        continue;
                    }
                }
                // 低于最低库存，生成库存预警信息
                if (stockStage.getMinimumStock() > wmsStorehouseStock.getQty()){
                    InventoryAlert inventoryAlert = new InventoryAlert();
                    inventoryAlert.setProductName(wmsStorehouseStock.getProductName());
                    inventoryAlert.setProductNo(wmsStorehouseStock.getProductNo());
                    inventoryAlert.setQty(wmsStorehouseStock.getQty());
                    inventoryAlert.setSafetyStock(stockStage.getSafetyStock());
                    inventoryAlert.setMaximumStock(stockStage.getMaximumStock());
                    inventoryAlert.setMinimumStock(stockStage.getMinimumStock());
                    inventoryAlert.setRemark("库存不足");
                    inventoryAlert.setStorehouseNo(wmsStorehouseStock.getStorehouseNo());
                    inventoryAlertAddList.add(inventoryAlert);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(inventoryAlertAddList)){
            this.inventoryAlertService.batchInsertInventoryAlert(inventoryAlertAddList);
        }
    }

    /**
     * 获取库存
     * @param storehouseNo
     * @param productNo
     * @param status
     * @return
     */
   public List<WmsStorehouseStock> getStock(String storehouseNo,String productNo,String status,String areaNo,String whetherMp,String workOrderNo){
       WmsStorehouseStock stock = new WmsStorehouseStock();
       if (StringUtils.isNotEmpty(status)){
           stock.setStatus(status);
       }
       if (StringUtils.isNotEmpty(storehouseNo)){
           stock.setStorehouseNo(storehouseNo);
       }
       if (StringUtils.isNotEmpty(areaNo)){
           stock.setStorehouseAreaNo(areaNo);
       }
       if (StringUtils.isNotEmpty(productNo)){
           stock.setProductNo(productNo);
       }
       if (StringUtils.isNotEmpty(whetherMp)){
           stock.setWhetherMp(whetherMp);
       }
       if (StringUtils.isNotEmpty(workOrderNo)){
           stock.setWorkOrderNo(workOrderNo);
       }
       List<WmsStorehouseStock> stockList = this.wmsStorehouseStockMapper.selectWmsStorehouseStockList(stock);
       return  stockList;
   }
    /**
     * 查询库存总览
     * @param bo
     * @return
     */
    @Override
    public List<InventoryOverviewVo> selectInventoryOverview(InventoryOverviewBo bo) {
        List<InventoryOverviewVo> list = wmsStorehouseStockMapper.selectInventoryOverview(bo);
        if (CollectionUtil.isNotEmpty(list)){
          for (InventoryOverviewVo vo : list){
              List<WmsStorehouseStock> stockList = this.getStock(bo.getStorehouseNo(),vo.getProductNo(),null,null,null,null);
              //正常状态数量
              Long stockN = 0L;
              //锁定状态数量
              Long stockS = 0l;
              //冻结状态数量
              Long stockD = 0l;
              //不良品状态数量
              Long stockNG = 0l;
              //退货品状态数量
              Long stockR = 0l;

              if (CollectionUtil.isNotEmpty(stockList)){
                  stockN = stockList.stream().filter(e->e.getStatus().equals(StorehouseStockStatusEnum.NORMAL.getCode())).mapToLong(WmsStorehouseStock::getQty).sum();
                  stockS = stockList.stream().filter(e->e.getStatus().equals(StorehouseStockStatusEnum.LOCK.getCode())).mapToLong(WmsStorehouseStock::getQty).sum();
                  stockD = stockList.stream().filter(e->e.getStatus().equals(StorehouseStockStatusEnum.FREEZE.getCode())).mapToLong(WmsStorehouseStock::getQty).sum();
                  stockNG = stockList.stream().filter(e->e.getStatus().equals(StorehouseStockStatusEnum.POOR.getCode())).mapToLong(WmsStorehouseStock::getQty).sum();
                  stockR = stockList.stream().filter(e->e.getStatus().equals(StorehouseStockStatusEnum.RETURNED.getCode())).mapToLong(WmsStorehouseStock::getQty).sum();
              }
              vo.setYjcLockTotalQty(stockS);
              vo.setYjcFreeTotalQty(stockD);
              vo.setYjcNGTotalQty(stockNG);
              vo.setYjcReturnTotalQty(stockR);
              vo.setYjcUseTotalQty(stockN+stockNG-vo.getYjcOccupyTotalQty()<0?0:stockN+stockNG-vo.getYjcOccupyTotalQty());

          }
        }
        return list;
    }

    @Override
    public List<WmsStorehouseStock> selectWmsStorehouseStockList2(WmsStorehouseStock wmsStorehouseStock) {
        return this.wmsStorehouseStockMapper.selectWmsStorehouseStockList2(wmsStorehouseStock);
    }

    @Override
    public List<InventoryOverviewVo> selectStockTotalQty(String storehouseNo, List<String> productNos) {
        return this.wmsStorehouseStockMapper.selectStockTotalQty(storehouseNo,productNos);
    }

    @Override
    public List<InventoryOverviewVo> selectOccupyTotalQty(String storehouseNo, List<String> productNos) {
        return this.wmsStorehouseStockMapper.selectOccupyTotalQty(storehouseNo,productNos);
    }

    @Override
    public List<WmsStorehouseStock> selectMpByWorkOrderNoAndProductNo(String whetherMp, String workOrderNo, String productNo) {
        WmsStorehouseStock query = new WmsStorehouseStock();
        query.setWhetherMp(whetherMp);
        query.setWorkOrderNo(workOrderNo);
        query.setProductNo(productNo);
        return this.selectWmsStorehouseStockList(query);
    }

    @Override
    public int updateContainerByBarcode(String barcode) {
        return this.wmsStorehouseStockMapper.updateContainerByBarcode(barcode);
    }

    /**
     * 查询线边仓出库空库位（按行列从小到大）
     * @return
     */
    @Override
    public List<WmsStorehouseStockVo> selectEmpWmsStorehouseOutStockList(){
        return wmsStorehouseStockMapper.selectEmpWmsStorehouseOutStockList();
    }

    @Override
    public List<WmsStorehouseStockVo> selectWmsStorehouseStockListByProductNos(OutStockQueryVo outStockQueryVo){
        return wmsStorehouseStockMapper.selectWmsStorehouseStockListByProductNos(outStockQueryVo);
    }

    /**
     * 绑定库存
     * @param location
     * @param shelfNo
     * @param trayNo
     * @param stockStatus
     * @param relBillNo
     * @param operation
     */
    public void bindStorehouseStock(WmsStorehouseLocation location,String shelfNo,String trayNo,
                                    String stockStatus,String relBillNo,InOutStockTypeEnum typeEnum,InOutStorageOperationEnum operation){
        WmsStorehouseStock stockQuery=new WmsStorehouseStock();
        stockQuery.setStorehouseLocationNo(location.getNo());
        stockQuery.setDelFlag("0");
        List<WmsStorehouseStock> storehouseStocks= wmsStorehouseStockMapper.selectWmsStorehouseStockList(stockQuery);
        if(storehouseStocks==null||storehouseStocks.size()==0){
            addStorehouseStock(location,shelfNo,trayNo,stockStatus,relBillNo,typeEnum,operation);
        }
        else{
            updateStorehouseStock(location,storehouseStocks.get(0),shelfNo,trayNo,stockStatus,relBillNo,typeEnum,operation);
        }

    }

    /**
     * 增加库存
     */
    private void addStorehouseStock(WmsStorehouseLocation location,String shelfNo,String trayNo,
             String stockStatus,String relBillNo,InOutStockTypeEnum typeEnum,InOutStorageOperationEnum operation){
        WmsStorehouseStock wmsStorehouseStock=new WmsStorehouseStock();
        wmsStorehouseStock.setStorehouseNo(location.getStorehouseNo());
        wmsStorehouseStock.setStorehouseAreaNo(location.getStorehouseAreaNo());
        wmsStorehouseStock.setStorehouseLocationNo(location.getNo());
        wmsStorehouseStock.setContainerNo(shelfNo);
        wmsStorehouseStock.setTrayNo(trayNo);
        wmsStorehouseStock.setStockStatus(stockStatus);
        wmsStorehouseStock.setNo(TableNoUtil.getNo(WmsStorehouseStock.class));
        wmsStorehouseStock.setCreateBy(SecurityUtils.getUsername());
        wmsStorehouseStock.setCreateTime(DateUtils.getNowDate());
        wmsStorehouseStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());
        wmsStorehouseStockMapper.insertWmsStorehouseStock(wmsStorehouseStock);

        WmsInOutStorage storage =new WmsInOutStorage();
        storage.setNo(TableNoUtil.getNo(WmsInOutStorage.class));
        storage.setStorehouseNo(location.getStorehouseNo());
        storage.setAreaNo(location.getStorehouseAreaNo());
        storage.setStorehouseLocationNo(location.getNo());
        storage.setContainerNo(shelfNo);
        storage.setTrayNo(trayNo);
        storage.setBusinessNo(relBillNo);
        storage.setOperation(operation.getCode());
        storage.setType((long)typeEnum.getCode());
        storage.setCreateBy(SecurityUtils.getUsername());
        storage.setCreateTime(DateUtils.getNowDate());
        wmsInOutStorageService.addWmsInOutStorage(storage);
    }

    /**
     * 更新库存
     */
    private void updateStorehouseStock(WmsStorehouseLocation location,WmsStorehouseStock wmsStorehouseStock,
              String shelfNo,String trayNo,String stockStatus,String relBillNo,InOutStockTypeEnum typeEnum,InOutStorageOperationEnum operation){
        wmsStorehouseStock.setStorehouseNo(location.getStorehouseNo());
        wmsStorehouseStock.setStorehouseAreaNo(location.getStorehouseAreaNo());
        wmsStorehouseStock.setStorehouseLocationNo(location.getNo());
        wmsStorehouseStock.setContainerNo(shelfNo);
        wmsStorehouseStock.setTrayNo(trayNo);
        wmsStorehouseStock.setStockStatus(stockStatus);
        wmsStorehouseStock.setUpdateBy(SecurityUtils.getUsername());
        wmsStorehouseStock.setUpdateTime(DateUtils.getNowDate());
        wmsStorehouseStock.setArriveTime(DateUtils.getNowDate());
        wmsStorehouseStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());

        wmsStorehouseStockMapper.updateWmsStorehouseStock(wmsStorehouseStock);

        WmsInOutStorage storage =new WmsInOutStorage();
        storage.setNo(TableNoUtil.getNo(WmsInOutStorage.class));
        storage.setStorehouseNo(location.getStorehouseNo());
        storage.setAreaNo(location.getStorehouseAreaNo());
        storage.setStorehouseLocationNo(location.getNo());
        storage.setContainerNo(shelfNo);
        storage.setTrayNo(trayNo);
        storage.setBusinessNo(relBillNo);
        storage.setOperation(operation.getCode());
        storage.setType((long)typeEnum.getCode());
        storage.setCreateBy(SecurityUtils.getUsername());
        storage.setCreateTime(DateUtils.getNowDate());
        wmsInOutStorageService.addWmsInOutStorage(storage);
    }
    /**
     * 处理AGV出库释放起点
     */
    @Override
    public void handleOutBinEvent(String source,AgvTaskDispatch taskDispatch){
        WmsStorehouseLocation sourceLocation=wmsStorehouseLocationService.selectWmsStorehouseLocationByNo(source);
        if(sourceLocation==null){
            throw new RuntimeException("源库位"+source+"不存在");
        }
        WmsStorehouseStock sourceStock=selectWmsStorehouseStockByLocationNo(source);
        if(sourceStock==null){
            throw new RuntimeException("源库位"+sourceLocation+"库存不存在");
        }
        InOutStorageOperationEnum operationEnum=getOperation(taskDispatch.getTaskType());
        sourceStock.setContainerNo("");
        sourceStock.setStockStatus("");
        sourceStock.setTrayNo("");
        sourceStock.setUpdateBy(SecurityUtils.getUsername());
        sourceStock.setUpdateTime(DateUtils.getNowDate());
        sourceStock.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
        wmsStorehouseStockMapper.updateWmsStorehouseStock(sourceStock);
        WmsInOutStorage sourceStorage =new WmsInOutStorage();
        sourceStorage.setNo(TableNoUtil.getNo(WmsInOutStorage.class));
        sourceStorage.setStorehouseNo(sourceLocation.getStorehouseNo());
        sourceStorage.setAreaNo(sourceLocation.getStorehouseAreaNo());
        sourceStorage.setStorehouseLocationNo(sourceLocation.getNo());
        sourceStorage.setContainerNo("");
        sourceStorage.setTrayNo("");
        sourceStorage.setBusinessNo(taskDispatch.getTaskCode());
        sourceStorage.setOperation(operationEnum.getCode());
        sourceStorage.setType((long)operationEnum.getCode());
        sourceStorage.setCreateBy(SecurityUtils.getUsername());
        sourceStorage.setCreateTime(DateUtils.getNowDate());
        wmsInOutStorageService.addWmsInOutStorage(sourceStorage);
    }
    /**
     * 处理AGV完结事件
     */
    @Override
    public void handleAgvEndEvent(String source,String dest, AgvTaskDispatch taskDispatch){
        WmsStorehouseStock sourceStock=selectWmsStorehouseStockByLocationNo(source);
        if(sourceStock==null){
            throw new RuntimeException("源库位"+source+"库存不存在");
        }
        WmsStorehouseLocation destLocation=wmsStorehouseLocationService.selectWmsStorehouseLocationByAgvPoint(dest);
        if(destLocation==null){
            throw new RuntimeException("目标库位"+dest+"不存在");
        }
        WmsStorehouseStock destStock=selectWmsStorehouseStockByLocationNo(dest);
        if(destStock==null){
            throw new RuntimeException("目标库位"+destLocation.getNo()+"库存不存在");
        }
        if(StringUtils.isNotEmpty(destStock.getContainerNo())){
            throw new RuntimeException("目标库位"+destLocation.getNo()+"存在"+destStock.getContainerNo());
        }
        InOutStorageOperationEnum operationEnum=getOperation(taskDispatch.getTaskType());

        Tray tray=trayService.selectTrayByTrayNo(taskDispatch.getTrayNo());
        String stockStatus="";
        if(tray!=null){
            stockStatus=tray.getStockStatus();
        }
        destStock.setContainerNo(taskDispatch.getShelfNo());
        destStock.setTrayNo(taskDispatch.getTrayNo());
        destStock.setArriveTime(DateUtils.getNowDate());
        destStock.setStockStatus(stockStatus);
        destStock.setUpdateBy(SecurityUtils.getUsername());
        destStock.setUpdateTime(DateUtils.getNowDate());
        //回库任务
        if(AgvEnum.TASK_TYPE.BACK.getCode().equals(taskDispatch.getTaskType())){
            //该托盘存在回库AGV任务，发现托盘还有分拣单未处理，直接锁定终点
            SplitBill query=new SplitBill();
            query.setTrayNo(tray.getTrayNo());
            query.setOrderStatus(OutOrderStatusEnum.NEW.getCode());
            query.setDelFlag("0");
            List<SplitBill> splitBills=splitBillService.selectSplitBillList(query);
            if(splitBills==null||splitBills.size()==0){
                if (StorehouseStockStatusEnum.LOCK.getCode().equals(destStock.getStatus())) {
                    destStock.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
                }
            }
            else{
                destStock.setStatus(StorehouseStockStatusEnum.LOCK.getCode());
            }
            //判断回库任务携带托盘是否还有物料
            TrayDetail trayDetail = new TrayDetail();
            trayDetail.setTrayNo(tray.getTrayNo());
            trayDetail.setDelFlag("0");
            List<TrayDetail> trayDetails=trayDetailService.selectTrayDetailList(trayDetail);
            if (trayDetails == null || trayDetails.size() == 0) {
                //删除货架和托盘的绑定关系
                bindRecordService.deleteBindRecordByParentNo(sourceStock.getContainerNo());
                destStock.setTrayNo("");
                destStock.setStockStatus("");
                destStock.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
            }
        }
        else {
            if (StorehouseStockStatusEnum.LOCK.getCode().equals(destStock.getStatus())) {
                destStock.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
            }
        }

        wmsStorehouseStockMapper.updateWmsStorehouseStock(destStock);
        WmsInOutStorage destStorage =new WmsInOutStorage();
        destStorage.setNo(TableNoUtil.getNo(WmsInOutStorage.class));
        destStorage.setStorehouseNo(destLocation.getStorehouseNo());
        destStorage.setAreaNo(destLocation.getStorehouseAreaNo());
        destStorage.setStorehouseLocationNo(destLocation.getNo());
        destStorage.setContainerNo(taskDispatch.getShelfNo());
        destStorage.setTrayNo(taskDispatch.getTrayNo());
        destStorage.setBusinessNo(taskDispatch.getTaskCode());
        destStorage.setOperation(operationEnum.getCode());
        destStorage.setType((long)operationEnum.getCode());
        destStorage.setCreateBy(SecurityUtils.getUsername());
        destStorage.setCreateTime(DateUtils.getNowDate());
        wmsInOutStorageService.addWmsInOutStorage(destStorage);
        //处理单据
        handleBill(taskDispatch);
    }

    /**
     * 获取Operation枚举
     */
    private InOutStorageOperationEnum getOperation(String taskType){
        switch (taskType){
            case "OUT":
                return InOutStorageOperationEnum.OUT;
            case "ADJUST":
                return InOutStorageOperationEnum.ADJUST;
            case "TRANSFER":
                return InOutStorageOperationEnum.TRANSFER;
            default:
                return InOutStorageOperationEnum.IN;
        }
    }

    /**
     * 处理单据
     * @param agvTaskDispatch agv任务
     */
    private void handleBill(AgvTaskDispatch agvTaskDispatch){
        if(AgvEnum.TASK_TYPE.IN.getCode().equals(agvTaskDispatch.getTaskType())){
            handleInStockBill(agvTaskDispatch);
        }
        else if(AgvEnum.TASK_TYPE.OUT.getCode().equals(agvTaskDispatch.getTaskType())){
            handleOutStockBill(agvTaskDispatch);
        }
        else if(AgvEnum.TASK_TYPE.ADJUST.getCode().equals(agvTaskDispatch.getTaskType())){
            handleAdjustLocationBill(agvTaskDispatch);
        }
        else if(AgvEnum.TASK_TYPE.BACK.getCode().equals(agvTaskDispatch.getTaskType())){
            handleReturnBill(agvTaskDispatch);
        }
    }
    /**
     * 处理入库单
     * @param taskDispatch agv任务
     */
    private void handleInStockBill(AgvTaskDispatch taskDispatch){
        InStockBill inStockBill=inStockBillService.selectInStockBillByNo(taskDispatch.getRefBillNo());
        if(inStockBill==null){
            return;
        }
        inStockBill.setOrderStatus(InOrderStatusEnum.ACCOMPLISH.getCode());
        inStockBill.setUpdateBy("RCS");
        inStockBillService.updateInStockBill(inStockBill);
        InStockBill query=new InStockBill();
        query.setRelOrderNo(inStockBill.getRelOrderNo());
        query.setDelFlag("0");
        List<InStockBill> allInStockBills=inStockBillService.selectInStockBillList(query);
        if(allInStockBills==null||allInStockBills.size()==0){
            return;
        }
        int completeCount=0;
        for (InStockBill item:allInStockBills){
            if(InOrderStatusEnum.ACCOMPLISH.getCode().equals(item.getOrderStatus())){
                completeCount++;
            }
        }
//        if(completeCount==allInStockBills.size()){
//            if(ErpBillTypeEnum.ADJUST_IN.getCode().equals(inStockBill.getBillType())){
//                AdjustInBill adjustInBill=adjustInBillService.selectAdjustInBillByNo(inStockBill.getRelOrderNo());
//                if(adjustInBill==null){
//                    return;
//                }
//                adjustInBill.setUpdateBy("RCS");
//                adjustInBill.setStatus(OrderStatusEnum.ACCOMPLISH.getCode());
//                adjustInBillService.updateAdjustInBill(adjustInBill);
//            }
//            else if(ErpBillTypeEnum.RECEIVE_PRODUCT.getCode().equals(inStockBill.getBillType())){
//                ReceiveProductBill receiveProductBill=receiveProductBillService.selectReceiveProductBillByNo(inStockBill.getRelOrderNo());
//                if(receiveProductBill==null){
//                    return;
//                }
//                receiveProductBill.setUpdateBy("RCS");
//                receiveProductBill.setStatus(OrderStatusEnum.ACCOMPLISH.getCode());
//                receiveProductBillService.updateReceiveProductBill(receiveProductBill);
//            }
//            else if(ErpBillTypeEnum.MODULATION_IN.getCode().equals(inStockBill.getBillType())){
//                ModulationInBill modulationInBill=modulationInBillService.selectModulationInBillByNo(inStockBill.getRelOrderNo());
//                if(modulationInBill==null){
//                    return;
//                }
//                modulationInBill.setUpdateBy("RCS");
//                modulationInBill.setStatus(OrderStatusEnum.ACCOMPLISH.getCode());
//                modulationInBillService.updateModulationInBill(modulationInBill);
//            }
//        }
    }

    /**
     * 处理出库单
     * @param taskDispatch agv任务
     */
    private void handleOutStockBill(AgvTaskDispatch taskDispatch){
        OutStockBill outStockBill =outStockBillService.selectOutStockBillByNo(taskDispatch.getRefBillNo());
        if(outStockBill ==null){
            return;
        }
        outStockBill.setUpdateBy("RCS");
        outStockBill.setOrderStatus(InOrderStatusEnum.ACCOMPLISH.getCode());
        outStockBillService.updateOutStockBill(outStockBill);
        OutStockBill query=new OutStockBill();
        query.setRelOrderNo(outStockBill.getRelOrderNo());
        query.setDelFlag("0");
        List<OutStockBill> allStockBills =outStockBillService.selectOutStockBillList(query);
        if(allStockBills ==null|| allStockBills.size()==0){
            return;
        }
        int completeCount=0;
        int splitCount=0;
        for (OutStockBill item: allStockBills){
            if(InOrderStatusEnum.ACCOMPLISH.getCode().equals(item.getOrderStatus())&&
                "0".equals(item.getIsSplit())){
                completeCount++;
            }
            else{
                splitCount++;
            }
        }
        if(completeCount== allStockBills.size()-splitCount){
            AdjustOutBill adjustOutBill =adjustOutBillService.selectAdjustOutBillByNo(outStockBill.getRelOrderNo());
            if(adjustOutBill ==null){
                return;
            }
            adjustOutBill.setUpdateBy(taskDispatch.getCreateBy());
            adjustOutBill.setStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
            adjustOutBillService.updateAdjustOutBill(adjustOutBill);
        }
    }
    /**
     * 处理调库单
     * @param taskDispatch agv任务
     */
    private void handleAdjustLocationBill(AgvTaskDispatch taskDispatch){
        AdjustLocationBill adjustLocationBill =adjustLocationBillService.selectAdjustLocationBillByNo(taskDispatch.getRefBillNo());
        if(adjustLocationBill ==null){
            return;
        }
        adjustLocationBill.setUpdateBy("RCS");
        adjustLocationBill.setOrderStatus(InOrderStatusEnum.ACCOMPLISH.getCode());
        adjustLocationBillService.updateAdjustLocationBill(adjustLocationBill);
    }
    /**
     * 处理调库单
     * @param taskDispatch agv任务
     */
    private void handleReturnBill(AgvTaskDispatch taskDispatch){
        ReturnStockBill returnStockBill =returnStockBillService.selectReturnStockBillByNo(taskDispatch.getRefBillNo());
        if(returnStockBill ==null){
            return;
        }
        returnStockBill.setUpdateBy("RCS");
        returnStockBill.setOrderStatus(InOrderStatusEnum.ACCOMPLISH.getCode());
        returnStockBillService.updateReturnStockBill(returnStockBill);
    }

    /**
     * 查询库存统计
     * @return
     */
    @Override
    public List<StorehouseStockAdjustDetailVo> selectWmsStorehouseStockAdjustList(){
        return wmsStorehouseStockMapper.selectWmsStorehouseStockAdjustList();
    }
    /**
     * 根据物料查询库存的批次号
     * @param productNo 物料编号
     * @return
     */
    @Override
    public List<String> selectWmsStorehouseStockBatchNoByProductNo(String productNo){
        return wmsStorehouseStockMapper.selectWmsStorehouseStockBatchNoByProductNo(productNo);
    }
    /**
     * 查询入库接驳空库位
     * @return
     */
    @Override
    public WmsStorehouseStockVo selectInDockingEmptyWmsStorehouseStock(){
        return wmsStorehouseStockMapper.selectInDockingEmptyWmsStorehouseStock();
    }
    /**
     * 查询出库接驳空料架
     * @return
     */
    @Override
    public WmsStorehouseStockVo selectOutDockingEmptyShelfStorehouseStock(){
        return wmsStorehouseStockMapper.selectOutDockingEmptyShelfStorehouseStock();
    }
    /**
     * 查询成品库空料架
     * @return
     */
    @Override
    public List<WmsStorehouseStockVo> selectProductEmptyShelfStorehouseStock(){
        return wmsStorehouseStockMapper.selectProductEmptyShelfStorehouseStock();
    }

    @Override
    public String bindContainerNo(WmsStorehouseStockVo vo) {
        if (StringUtils.isEmpty(vo.getStorehouseLocationNo())) {
            return "库位编号不能为空";
        }
        if (StringUtils.isEmpty(vo.getContainerNo())) {
            return "料架编号不能为空";
        } else if (!StringUtils.startsWith(vo.getContainerNo(), "H")) {
            return "料架号不正确";
        }
        if (StringUtils.isNotEmpty(vo.getTrayNo()) && !StringUtils.startsWith(vo.getTrayNo(), "T")) {
            return "托盘号不正确";
        }
        WmsStorehouseLocation location = wmsStorehouseLocationService.selectWmsStorehouseLocationByNo(vo.getStorehouseLocationNo());
        if(ObjectUtil.isEmpty(location)){
            return "没有查询到库位" + vo.getStorehouseLocationNo();
        }
        //库位是否存在正在执行的任务
        List<AgvTaskDispatch> startTasks = agvTaskDispatchService.selectAgvTaskDispatchListByStartPoint(vo.getStorehouseLocationNo());
        if (CollectionUtil.isNotEmpty(startTasks)) {
            return "起点有正在执行的任务" + vo.getStorehouseLocationNo();
        }
        List<AgvTaskDispatch> endTasks = agvTaskDispatchService.selectAgvTaskDispatchListByEndPoint(vo.getStorehouseLocationNo());
        if (CollectionUtil.isNotEmpty(endTasks)) {
            return "终点有正在执行的任务" + vo.getStorehouseLocationNo();
        }
        WmsStorehouseStockVo stockVo = wmsStorehouseStockMapper.selectStorehouseStockByLocationNo(vo.getStorehouseLocationNo());
        if(ObjectUtil.isNotEmpty(stockVo) && StringUtils.isNotEmpty(stockVo.getContainerNo())){
            return "库位已经绑定料架" + stockVo.getContainerNo();
        }
        if(ObjectUtil.isNotEmpty(stockVo) && StringUtils.isNotEmpty(stockVo.getTrayNo())){
            return "库位已经绑定托盘" + stockVo.getTrayNo();
        }
        WmsStorehouseStock stock = wmsStorehouseStockMapper.selectWmsStorehouseStockByContainerNo(vo.getContainerNo());
        if(ObjectUtil.isNotEmpty(stock)){
            return "料架已经绑定" + stock.getStorehouseLocationNo();
        }
        if(StringUtils.isNotEmpty(vo.getTrayNo())) {
            stock = wmsStorehouseStockMapper.selectWmsStorehouseStockByTrayNo(vo.getTrayNo());
            if (ObjectUtil.isNotEmpty(stock)) {
                return "托盘已经绑定" + stock.getStorehouseLocationNo();
            }
        }
        int result = wmsStorehouseStockMapper.bindContainerNo(vo);
        if (result > 0) {
            return "绑定成功";
        }
        return "绑定失败";
    }

    @Override
    public AjaxResult unbindContainerNo(WmsStorehouseStockVo vo) {
        if (StringUtils.isEmpty(vo.getContainerNo())) {
            return AjaxResult.error("料架编号不能为空");
        }
        WmsStorehouseStock stock = wmsStorehouseStockMapper.selectWmsStorehouseStockByContainerNo(vo.getContainerNo());
        if (ObjectUtil.isEmpty(stock)) {
            return AjaxResult.error("料架没有绑定货位");
        }
        if (!StringUtils.equals(stock.getStatus(), StorehouseStockStatusEnum.NORMAL.getCode()) && agvTaskDispatchService.queryRunningTaskByShelfNo(vo.getContainerNo()) > 0) {
            return AjaxResult.error("存在AGV搬运任务，不可解绑");
        }
        int result = wmsStorehouseStockMapper.unbindContainerNo(vo);
        if (result > 0) {
            return AjaxResult.success("解绑成功");
        }
        return AjaxResult.error("解绑失败");
    }

    @Override
    public AjaxResult unbindTrayNo(WmsStorehouseStockVo vo) {
        if (StringUtils.isEmpty(vo.getContainerNo())) {
            return AjaxResult.error("料架编号不能为空");
        }
        WmsStorehouseStock stock = wmsStorehouseStockMapper.selectWmsStorehouseStockByContainerNo(vo.getContainerNo());
        if (ObjectUtil.isEmpty(stock)) {
            return AjaxResult.error("料架没有绑定货位");
        }
        if (ObjectUtil.isEmpty(stock.getTrayNo())) {
            return AjaxResult.error("料架没有绑定托盘");
        }
        if (!StringUtils.equals(stock.getStatus(), StorehouseStockStatusEnum.NORMAL.getCode()) && agvTaskDispatchService.queryRunningTaskByShelfNo(vo.getContainerNo()) > 0) {
            return AjaxResult.error("存在AGV搬运任务，不可解绑");
        }
        bindRecordService.deleteBindRecordByParentNo(stock.getContainerNo());
        int result = wmsStorehouseStockMapper.unbindTrayNo(vo);
        if (result > 0) {
            return AjaxResult.success("解绑成功");
        }
        return AjaxResult.error("解绑失败");
    }

    @Override
    public WmsStorehouseStock selectStockInfosByContainerNo(String containerNo) {
        return wmsStorehouseStockMapper.selectStockInfosByContainerNo(containerNo);
    }
}
